from functools import wraps
from random import choice
from time import sleep
import time

from Common.ReadYaml import ConfigYaml


class ReExecution:

    def __init__(self, fun, code_msg="success", response_key='data', response_list='list', switch=True, special="", key='',
                 appoint=False, mode="in",  status_key='', value=''):
        '''
        :param fun:  回调函数
        :param status:  状态
        :param response_key:  响应data数据键
        :param response_list:  响应列表数据
        :param value:  需要获取的值
        '''
        self.fun = fun
        if callable(self.fun):
            self.name = self.fun.__name__
        else:
            self.name = "未知函数"
        self.code_msg = code_msg
        self.response_key = response_key
        self.response_list = response_list
        self.switch = switch
        self.special = special
        self.key = key
        self.appoint = appoint
        self.mode = mode
        self.status_key = status_key
        self.value = value
        self.list_data = []

    def __call__(self, method):
        '''
        :param method:
        :return:
        '''
        @wraps(method)
        def wrapper(*args, **kwargs):
            data_info = ''
            result = method(*args, **kwargs)
            if result.get(self.code_msg):
                if self.response_key:
                    if self.response_list:
                        data_list = result.get(self.response_key).get(self.response_list)
                        if data_list and self.fun:
                            if self.switch:
                                return data_list

                            elif self.appoint and self.mode == "in":
                                for list_value in data_list:
                                    if self.status_key:
                                        if self.special in list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                            self.list_data.append(list_value)

                                    else:
                                        if self.special in list_value.get(self.key):
                                            self.list_data.append(list_value)

                                if not self.list_data:
                                    self.fun(*args)
                                    result = method(*args, **kwargs)
                                    data_list = result.get(self.response_key).get(self.response_list)
                                    for list_value in data_list:
                                        if self.status_key:
                                            if self.special in list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                                self.list_data.append(list_value)

                                        else:
                                            if self.special in list_value.get(self.key):
                                                self.list_data.append(list_value)

                                return self.list_data

                            elif self.appoint and self.mode == "equal":
                                for list_value in data_list:
                                    if self.status_key:
                                        if self.special == list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                            self.list_data.append(list_value)

                                    else:
                                        if self.special == list_value.get(self.key):
                                            self.list_data.append(list_value)

                                if not self.list_data:
                                    self.fun(*args)
                                    result = method(*args, **kwargs)
                                    data_list = result.get(self.response_key).get(self.response_list)
                                    for list_value in data_list:
                                        if self.status_key:
                                            if self.special == list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                                self.list_data.append(list_value)

                                        else:
                                            if self.special == list_value.get(self.key):
                                                self.list_data.append(list_value)

                                return self.list_data

                            else:
                                for value in data_list:
                                    if value.get(self.key) == self.special:
                                        data_info = value

                                return data_info

                        elif data_list and not self.fun:

                            if self.switch:
                                return data_list

                            elif self.appoint:
                                if self.mode == "in":
                                    for list_value in data_list:
                                        if self.status_key:
                                            if self.special in list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                                self.list_data.append(list_value)

                                        else:
                                            if self.special in list_value.get(self.key):
                                                self.list_data.append(list_value)

                                    return self.list_data

                                elif self.mode == "equal":
                                    for list_value in data_list:
                                        if self.status_key:
                                            if self.special == list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                                self.list_data.append(list_value)

                                        else:
                                            if self.special == list_value.get(self.key):
                                                self.list_data.append(list_value)

                                    return self.list_data

                            else:
                                for value in data_list:
                                    if value.get(self.key) == self.special:
                                        data_info = value

                                return data_info

                        elif not data_list and self.fun:
                            self.fun(*args)
                            result = method(*args, **kwargs)
                            data_list = result.get(self.response_key).get(self.response_list)
                            if self.switch:
                                return data_list

                            elif self.appoint and self.mode == "in":
                                for list_value in data_list:
                                    if self.status_key:
                                        if self.special in list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                            self.list_data.append(list_value)

                                    else:
                                        if self.special in list_value.get(self.key):
                                            self.list_data.append(list_value)

                                if not self.list_data:
                                    self.fun(*args)
                                    result = method(*args, **kwargs)
                                    data_list = result.get(self.response_key).get(self.response_list)
                                    for list_value in data_list:
                                        if self.status_key:
                                            if self.special in list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                                self.list_data.append(list_value)

                                        else:
                                            if self.special in list_value.get(self.key):
                                                self.list_data.append(list_value)

                                return self.list_data

                            elif self.appoint and self.mode == "equal":
                                for list_value in data_list:
                                    if self.status_key:
                                        if self.special == list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                            self.list_data.append(list_value)

                                    else:
                                        if self.special == list_value.get(self.key):
                                            self.list_data.append(list_value)

                                if not self.list_data:
                                    self.fun(*args)
                                    result = method(*args, **kwargs)
                                    data_list = result.get(self.response_key).get(self.response_list)
                                    for list_value in data_list:
                                        if self.status_key:
                                            if self.special == list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                                self.list_data.append(list_value)

                                        else:
                                            if self.special == list_value.get(self.key):
                                                self.list_data.append(list_value)

                                return self.list_data

                            else:
                                for value in data_list:
                                    if value.get(self.key) == self.special:
                                        data_info = value

                            return data_info

                    else:
                        data_list = result.get(self.response_key)
                        if self.switch:
                            return data_list

                        elif self.appoint and self.mode == "in":
                            for list_value in data_list:
                                if self.status_key:
                                    if self.special in list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                        self.list_data.append(list_value)

                                else:
                                    if self.special in list_value.get(self.key):
                                        self.list_data.append(list_value)

                            if not self.list_data:
                                self.fun(*args)
                                result = method(*args, **kwargs)
                                data_list = result.get(self.response_key)
                                for list_value in data_list:
                                    if self.status_key:
                                        if self.special in list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                            self.list_data.append(list_value)

                                    else:
                                        if self.special in list_value.get(self.key):
                                            self.list_data.append(list_value)

                            return self.list_data

                        elif self.appoint and self.mode == "equal":
                            for list_value in data_list:
                                if self.status_key:
                                    if self.special == list_value.get(self.key) and self.value == list_value.get(
                                            self.status_key):
                                        self.list_data.append(list_value)

                                else:
                                    if self.special == list_value.get(self.key):
                                        self.list_data.append(list_value)

                            if not self.list_data:
                                self.fun(*args)
                                result = method(*args, **kwargs)
                                data_list = result.get(self.response_key)
                                for list_value in data_list:
                                    if self.status_key:
                                        if self.special == list_value.get(self.key) and self.value == list_value.get(self.status_key):
                                            self.list_data.append(list_value)
                                    else:
                                        if self.special == list_value.get(self.key):
                                            self.list_data.append(list_value)

                            return self.list_data

                        else:
                            for value in data_list:
                                if value.get(self.key) == self.special:
                                    data_info = value

                            return data_info
            else:
                raise ValueError(f"{self.name}该接口异常，请检查...")

        return wrapper


class NumberCycles:
    def __init__(self, time_sleep=0):
        '''
        公共方法未获取到数据，重跑机制
        :param setUp:
        '''
        self.start_time = int(time.time())
        self.cycles = ConfigYaml(key='cycles').base_config       #重跑次数
        self.time_sleep = time_sleep

    def __call__(self, method):
        '''
        类装饰器，定义重跑结构
        :param method:
        :return:
        '''

        @wraps(method)
        def execute(*args, **kwargs):
            result = method(*args, **kwargs)
            if not result:
                while True:
                    result = method(*args, **kwargs)
                    sleep(self.time_sleep)
                    self.end_time = int(time.time())
                    result_time = self.end_time - self.start_time

                    if result or result_time > 15:
                        return result

            return result

        return execute
